// The -*- C++ -*- math functions header.
// This file is part of the GNU ANSI C++ Library.

#ifndef __CMATH__
#define __CMATH__
#include <_G_config.h>
#include <math.h>

#ifdef __GNUG__
#pragma interface "cmath"
#endif

extern "C++" {
#if 0
float acos (float);
float asin (float);
float atan (float);
float atan2(float, float);
float ceil (float);
float cos  (float);
float cosh (float);
float exp  (float);
float fabs (float);
float floor(float);
float fmod (float, float);
float frexp(float, int*);
float modf (float, float*);
float ldexp(float, int);
float log  (float);
float log10(float);
float pow  (float, float);
float pow  (float, int);
float sin  (float);
float sinh (float);
float sqrt (float);
float tan  (float);
float tanh (float);
#endif

inline float  abs (float  x) { return fabs (x); }
#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */
inline double abs (double x) { return fabs (x); }
#endif

#if 0
double pow(double, int);

long double acos (long double);
long double asin (long double);
long double atan (long double);
long double atan2(long double, long double);
long double ceil (long double);
long double cos  (long double);
long double cosh (long double);
long double exp  (long double);
long double fabs (long double);
long double floor(long double);
long double frexp(long double, int*);
long double fmod (long double, long double);
long double frexp(long double, int*);
long double log  (long double);
long double log10(long double);
long double modf (long double, long double*);
long double pow  (long double, long double);
long double pow  (long double, int);
long double sin  (long double);
long double sinh (long double);
long double sqrt (long double);
long double tan  (long double);
long double tanh (long double);
#endif
inline long double abs (long double x) { return fabs (x); }

} // extern "C++"

// These are possible macros imported from C99-land.
#undef fpclassify
#undef isfinite
#undef isinf
#undef isnan
#undef isnormal
#undef signbit
#undef isgreater
#undef isgreaterequal
#undef isless
#undef islessequal
#undef islessgreater
#undef isunordered

namespace std
{
  inline int fpclassify(float __x) { return __fpclassifyf(__x); }
  inline int fpclassify(double __x) { return __fpclassify(__x); }
  inline int fpclassify(long double __x) { return __fpclassifyl(__x); }

  inline bool isfinite(float __x) { return __finitef(__x); }
  inline bool isfinite(double __x) { return __finite(__x); }
  inline bool isfinite(long double __x) { return __finitel(__x); }

  inline bool isinf(float __x) { return __isinff(__x); }
  inline bool isinf(double __x) { return __isinf(__x); }
  inline bool isinf(long double __x) { return __isinfl(__x); }

  inline bool isnan(float __x) { return __isnanf(__x); }
  inline bool isnan(double __x) { return __isnan(__x); }
  inline bool isnan(long double __x) { return __isnanl(__x); }

  inline bool isnormal(float __x) { return __fpclassifyf(__x) == FP_NORMAL; }
  inline bool isnormal(double __x) { return __fpclassify(__x) == FP_NORMAL; }
  inline bool isnormal(long double __x) { return __fpclassifyl(__x) == FP_NORMAL; }

  inline bool signbit(float __x) { return __signbitf(__x); }
  inline bool signbit(double __x) { return __signbit(__x); }
  inline bool signbit(long double __x) { return __signbitl(__x); }

#undef _wrap_expr_typeof
	#define _wrap_expr_typeof(x, y, body) ({	\
		__typeof(x) X = (x);					\
		__typeof(y) Y = (y);					\
		return (body);})

  inline bool isgreater(float __x, float __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X > Y);
  };
  inline bool isgreater(double __x, double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X > Y);
  };
  inline bool isgreater(long double __x, long double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X > Y);
  };

  inline bool isgreaterequal(float __x, float __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X >= Y);
  };
  inline bool isgreaterequal(double __x, double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X >= Y);
  };
  inline bool isgreaterequal(long double __x, long double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X >= Y);
  };

  inline bool isless(float __x, float __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X < Y);
  };
  inline bool isless(double __x, double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X < Y);
  };
  inline bool isless(long double __x, long double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X < Y);
  };

  inline bool islessequal(float __x, float __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X <= Y);
  };
  inline bool islessequal(double __x, double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X <= Y);
  };
  inline bool islessequal(long double __x, long double __y) {
    _wrap_expr_typeof(__x, __y, !isnan(X) && !isnan(Y) && X <= Y);
  };

  inline bool islessgeater(float __x, float __y) {
    _wrap_expr_typeof(__x, __y, X < Y || Y < X);
  };
  inline bool islessgreater(double __x, double __y) {
    _wrap_expr_typeof(__x, __y, X < Y || Y < X);
  };
  inline bool islessgreater(long double __x, long double __y) {
    _wrap_expr_typeof(__x, __y, X < Y || Y < X);
  };

  inline bool isunordered(float __x, float __y) {
    _wrap_expr_typeof(__x, __y, isnan(X) || isnan(Y));
  };
  inline bool isunordered(double __x, double __y) {
    _wrap_expr_typeof(__x, __y, isnan(X) || isnan(Y));
  };
  inline bool isunordered(long double __x, long double __y) {
    _wrap_expr_typeof(__x, __y, isnan(X) || isnan(Y));
  };

#undef _wrap_expr_typeof

} // namespace

#endif
